﻿using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Security.Claims;
using System.Web.Http;
using Sustainalytics.Claims;
using Sustainalytics.Entities;

namespace Sustainalytics.ProductInvolvement.Service
{
    public static class PIClaimsCheckerExtensions
    {
        //Company/PI or SP claim && at least one of the claims

        //can be used for both CompanyAssessmentsController and CompanyAssessmentShortReportsController 
        public static List<string> GetClaimedCompanyIndicators(this IClaimsChecker claimsChecker, ApiController ctrl, IEnumerable<string> piIndicators, string routeKey)
        {
            List<string> claimedPIIndicators = new List<string>();

            foreach (string indValue in piIndicators)
            {
                if (claimsChecker.Validate(ctrl, new List<ResourceParameters> { new ResourceParameters { Key = routeKey, Value = indValue } }))
                {
                    claimedPIIndicators.Add(indValue.ToUpperInvariant());
                }
            }

            return claimedPIIndicators;
        }

        public static bool ValidateCompanyPI(this IClaimsChecker claimsChecker, ApiController ctrl, IEnumerable<string> piIndicators, string routeKey)
        {
            string piIndicator;
            var queryDic = ctrl.Request.GetQueryNameValuePairs().ToDictionary(el => el.Key, el => el.Value);
            queryDic.TryGetValue(routeKey, out piIndicator);

            bool valid;
            bool atLeastOnePIClaim = false;

            if (string.IsNullOrEmpty(piIndicator))
            {

                bool hasCompanyPI = claimsChecker.Validate(ctrl, new List<ResourceParameters> { new ResourceParameters { Key = routeKey, Value = "companyreport" } });

                foreach (string indValue in piIndicators)
                {
                    bool claimedInd = claimsChecker.Validate(ctrl, new List<ResourceParameters> { new ResourceParameters { Key = routeKey, Value = indValue } });
                    atLeastOnePIClaim = atLeastOnePIClaim || claimedInd;
                }

                valid = hasCompanyPI && atLeastOnePIClaim;
            }
            else
            {
                // check specific PI Indicator claim
                valid = claimsChecker.Validate(ctrl, new List<ResourceParameters> { new ResourceParameters { Key = routeKey, Value = piIndicator } });
            }

            return valid;
        }


        //(Research/PI claim && at least one of the 18 PI claims) || Compliance/Sanctions claim
        public static bool ValidateMultiCompanyPI(this IClaimsChecker claimsChecker, ApiController ctrl, IEnumerable<string> piIndicators, string routeKey)
        {
            //string piIndicator;

            var queryDic = ctrl.Request.GetQueryNameValuePairs();

            //queryDic.TryGetValue(routeKey, out piIndicator);

            bool valid;
            bool atLeastOnePIClaim = false;
            string piIndicator = queryDic.Where(x => x.Key == routeKey).Select(x=>x.Value).FirstOrDefault();
            if (string.IsNullOrEmpty(piIndicator))
            {
                bool hasMultiCompanyPI = claimsChecker.Validate(ctrl, new List<ResourceParameters> { new ResourceParameters { Key = routeKey, Value = "multicompanyreport" } });
                bool hasComplianceSanctions = claimsChecker.Validate(ctrl, new List<ResourceParameters> { new ResourceParameters { Key = routeKey, Value = "sanctions" } });

                foreach (string indValue in piIndicators)
                {
                    bool claimedInd = claimsChecker.Validate(ctrl, new List<ResourceParameters> { new ResourceParameters { Key = routeKey, Value = indValue } });
                    atLeastOnePIClaim = atLeastOnePIClaim || claimedInd;
                }

                valid = (hasMultiCompanyPI && atLeastOnePIClaim) || hasComplianceSanctions;
            }
            else
            {
                // check specific PI Indicator claim
                valid = claimsChecker.Validate(ctrl, new List<ResourceParameters> { new ResourceParameters { Key = routeKey, Value = piIndicator } });
            }

            return valid;
        }

        public static bool Validate(this IClaimsChecker claimsChecker, ApiController ctrl, List<ResourceParameters> parameters)
        {
            // get current principal
            var principal = (ClaimsPrincipal)ctrl.User;

            // get route prefix
            object[] attrs = ctrl.GetType().GetCustomAttributes(typeof(RoutePrefixAttribute), false);
            RoutePrefixAttribute routePrefixAttrs = attrs == null || attrs.Length == 0 ? null : attrs.Select(a => (RoutePrefixAttribute)a).FirstOrDefault();

            // get HTTP Method
            string httpMethod = ctrl.Request.Method.Method;

            bool valid = claimsChecker.Validate(
                claimsPrincipal: principal,
                resource: routePrefixAttrs == null ? null : routePrefixAttrs.Prefix,
                verb: httpMethod,
                parameters: parameters);

            return valid;
        }
    }
}

